/*
 * Lock.h
 *
 *  Created on: Jan 25, 2013
 *      Author: Lucifer
 */
#ifndef	__BFX_LOCK_H__
#define	__BFX_LOCK_H__

namespace BFX
{

//////////////////////////////////////////////////////////////////////////////
// class: Spinlock
//
// PURPOSE:
//   spinlock class that contains constructor and out of line spinloop.
//

class BFX_API SpinLock
{
private:
	// m_nLock has to be the fist data member in the class
	volatile LONG	m_nLock;					// LONG used in interlocked exchange

	enum SpinLockState
	{
		UnInitialized	= 0,
		BeingInitialized,
		Initialized
	};

	volatile LONG	m_Initialized;	// To verify initialized
	// And initialize once

public:
	SpinLock ();
	~SpinLock ();

private:
	// initialize lock
	void Init();
	void SpinToAcquire (); // out of line call spins
	bool GetLockNoWait();   // Acquire lock, fail-fast

	// The following 2 APIs should remain private.  We want all entry/exit code to
	// occur via holders, so that exceptions will be sure to release the lock.
	// But sometimes will need to access them separately.
public:
	void GetLock ();        // Acquire lock, blocks if unsuccessful
	void FreeLock ();       // Release lock

public:
	typedef ObjectHolderT <SpinLock, &SpinLock::GetLock, &SpinLock::FreeLock> Holder;
};

typedef SpinLock::Holder SpinLockHolder;

//////////////////////////////////////////////////////////////////////////////
//

class BFX_API Mutex
{
public:
	Mutex();
	virtual ~Mutex();

	bool TryLock();
	bool IsLocked();

	// The following 2 APIs should remain private.  We want all entry/exit code to
	// occur via holders, so that exceptions will be sure to release the lock.
	// But sometimes will need to access them separately.
	void Lock();
	void Unlock();

public:
	typedef ObjectHolderT <Mutex, &Mutex::Lock, &Mutex::Unlock> Holder;

private:
#ifdef	_WIN32
	CRITICAL_SECTION	m_CritSec;
#else
	INT32	m_nLockCount;
	INT32	m_nRecursionCount;
	HANDLE	m_hOwningThread;
	HANDLE	m_hLockSemaphore;
	UINT32	m_nSpinCount;
#endif
};

typedef Mutex::Holder MutexHolder;

} /* namespace BFX */

#endif	//	__BFX_LOCK_H__
